home *** CD-ROM | disk | FTP | other *** search
- /*P*/
- /****************************************************************/
- /* */
- /* get_pre_command, accept */
- /* */
- /* These two routines handle the doubling cube. get_pre_command */
- /* fills in a buffer if a double should be made by the */
- /* person specified (this is the same routine for both black */
- /* and white). Accept returns a char of eother 'Y' or 'N', as */
- /* if the user had typed it in at the terminal. */
- /* */
- /****************************************************************/
-
- #include <stdio.h>
- #include "bkg.h"
-
- get_pre_command( who, buf, owned, value )
-
- int who;
- char buf[];
- int owned, value;
-
- {
-
- int b_count, w_count, diff, my_count, calc;
-
- buf[ 0 ] = '\0';
-
- /* Only double if the cube is either in the */
- /* middle, or is my half of the board. */
-
- if ( ( value < 64 ) &&
- ( ( owned == who ) ||
- ( owned == NOBODY ) ) )
- {
-
- get_counts( who, &b_count, &w_count, &diff, &my_count );
-
- /* If your lead is 7.5% of your count, make */
- /* a first double. If it is 10.0% make a later */
- /* double. */
-
- calc = ( diff * 100 ) / my_count;
-
- if ( ( value == 1 ) &&
- ( calc >= 8 ) )
- strcpy( buf, "double" );
- else
- if ( calc >= 10 )
- strcpy( buf, "double" );
-
- } /* look at situation */
-
- } /* get_pre_command */
-
- char accept( who )
-
- {
-
- int b_count, w_count, diff, my_count, calc;
-
- get_counts( who, &b_count, &w_count, &diff, &my_count );
-
- /* Accept a double any time you are less than */
- /* 15% behind in the game. */
-
- calc = ( diff * 100 ) / my_count;
-
- if ( calc > -15 )
- return( 'Y' );
- else
- return( 'N' );
-
- } /* accept */
-
- /*P*/
- /****************************************************************/
- /* */
- /* get_counts */
- /* */
- /* Calculate the counts on the board and return these values. */
- /* "who" indicates the player requesting the counts. We return */
- /* that players count in "my_count", and both in the others. */
- /* */
- /****************************************************************/
-
- get_counts( who, b_count, w_count, diff, my_count )
-
- int who, *b_count, *w_count, *diff, *my_count;
-
- {
-
- int i;
-
- *b_count = *w_count = 0;
-
- for( i = B_BAR; i < 25; i++ )
- *b_count += ( 25 - i ) * board[ i ][ BLACK ];
-
- for( i = W_BAR; i; i-- )
- *w_count += i * board[ i ][ WHITE ];
-
- if ( who == BLACK )
- *diff = *w_count - *b_count;
- else
- *diff = *b_count - *w_count;
-
- *my_count = ( who == WHITE ) ? *w_count : *b_count;
-
- } /* get_count */
-
- /*P*/
- /****************************************************************/
- /* */
- /* eval */
- /* */
- /* These sections control board position evaluation. An integer */
- /* is returned to the caller denoting the worth of a particular */
- /* board. The passed in board is a temp-type, that is, it is */
- /* 3 deep. The [ 2 ] part of the array contains hit men that */
- /* have been removed. If b_eval is called, for example, then */
- /* test[ 15 ][ 2 ] tells if any white men have been bumped off */
- /* of the 15 spot. */
- /* */
- /* It is up to the caller to make sure that the test board was */
- /* "gotten to" via a legal move. See movegen.c for details. */
- /* */
- /* Needless to say, this is where the "smarts" are. These two */
- /* functions are very critical to a "good" game player. Since */
- /* I'm a 1/2 way good player, I have made these as good as I */
- /* know how; however, there is always room for a lot of late */
- /* improvement by anyone who is more familiar with the "theory" */
- /* than I am (that is just about anyone...). */
- /* */
- /****************************************************************/
-
- /****************************************************************/
- /* */
- /* b_eval */
- /* */
- /* Evaluate the test board according to black's favor. Return */
- /* an integer denoting how good the position is. Positive is */
- /* better. The highest eval number is the "best" move. */
- /* */
- /****************************************************************/
-
- b_eval( test, count )
-
- int test[ SIZE ][ 3 ], count;
-
- {
-
- char buf[ 80 ];
- int i, j, watch_it, score, quad, end_game, hit_val;
-
- score = 0;
-
- /* If we are heavy into testing, spit */
- /* out the entire board in decimal. */
-
- if ( debug == 3 )
- {
- char_at( 21, 0, CTEOL, 0x07 );
- for( i = 0; i < 26; i++ )
- printf( "%02d ", test[ i ][ WHITE ] );
- char_at( 22, 0, CTEOL, 0x07 );
- for( i = 0; i < 26; i++ )
- printf( "%02d ", test[ i ][ BLACK ] );
- char_at( 23, 0, CTEOL, 0x07 );
- for( i = 0; i < 26; i++ )
- printf( "%02d ", test[ i ][ 2 ] );
- raw_keyboard();
- }
-
- /* Let them know we are still working */
- /* on a solution... */
-
- if ( count == 80 )
- write_at( 15, 65, "Thinking...", TEXT_COLOR );
-
- /* Test exception # 0 - we are in the */
- /* white's inner table, but we're going */
- /* to lose bad. in that case, we want */
- /* to hit anything we can! */
-
- for ( i = 25; i > 10; i-- )
- if ( test[ i ][ WHITE ] )
- break;
-
- if ( i == 10 )
- for ( ; i; i-- )
- if ( test[ i ][ 2 ] )
- score = 30000;
-
- /* Look for another exception - we may */
- /* be almost off of the board, but then */
- /* leave one and only one man open on a */
- /* particular bar. If that's the case, */
- /* we don't want to do that... */
-
- for( i = 24; i > 16; i-- )
- if ( test[ i ][ BLACK ] == 1 )
- break;
-
- if ( i > 16 )
- {
-
- watch_it = FALSE;
-
- for( j = 24; j; j-- )
- if ( test[ j ][ 2 ] )
- {
- watch_it = TRUE;
- break;
- }
-
- for( j = 25; j > i; j-- )
- if ( test[ j ][ WHITE ] )
- {
- watch_it = TRUE;
- break;
- }
-
- for( j = 16; j; j-- )
- if ( test[ j ][ BLACK ] )
- {
- watch_it = FALSE;
- break;
- }
-
- if ( watch_it )
- score = -30000;
-
- } /* exception 1 */
-
- /* Detect the end-game situation. */
- /* According to a Scientific American */
- /* article about 5 years ago, this */
- /* should be a smooth transition, and */
- /* not a boolean. Future fix? */
-
- for( i = 1; i < 25; i++ )
- if ( test[ i ][ BLACK ] )
- break;
-
- for( end_game = TRUE; i < 25; i++ )
- if ( ( test[ i ][ WHITE ] ) ||
- ( test[ i ][ 2 ] ) )
- {
- end_game = FALSE;
- break;
- }
-
- if ( end_game )
- {
-
- for( i = 1; i < 19; i++ )
- score -= test[ i ][ BLACK ] * ( 25 - i );
- for( ; i < 25; i++ )
- score -= test[ i ][ BLACK ];
- return( score );
-
- } /* end_game */
- else
- {
-
- for( i = 24; i; i-- )
- {
-
- quad = ( ( 24 - i ) / 6 ) + 1;
-
- /* If there is only one black player */
- /* here, then it is a disadvantage. But */
- /* how much depends on the possability */
- /* of getting hit, and where it is. */
-
- if ( test[ i ][ BLACK ] == 1 )
- {
-
- /* Check out every potential hitter */
-
- hit_val = ( i - 7 );
- for( j = i + 1; ( j < 26 ) && ( j < i + 12 ); j++ )
- switch( test[ j ][ WHITE ] )
- {
-
- case 0: break;
-
-
- case 1: hit_val += prob[ j - i ];
- break;
-
- case 2: hit_val += prob[ j - i ] / 2;
- break;
-
- default: hit_val += prob[ j - i ] * 2;
-
- } /* switch */
-
- /* If it's by the outer table, it's */
- /* not bad, since we come right back. */
-
- score -= hit_val * ( 4 - quad );
-
- } /* if */
-
- if ( test[ i ][ BLACK ] > 1 )
- {
- score += ( i - 7 );
- score += ( 4 - quad ) * 5;
- }
-
- /* Hit the white guys? */
-
- if ( test[ i ][ 2 ] )
- {
-
- score += quad * 15;
- for( j = 24; j > 16; j-- )
- if ( test[ j ][ BLACK ] > 1 )
- score += 5;
- else
- if ( test[ j ][ BLACK ] == 1 )
- score -= 3;
-
- } /* test inner tbl */
-
- } /* for i */
-
- return( score );
-
- } /* not end game */
-
- } /* b_eval */
-
- /*P*/
- /****************************************************************/
- /* */
- /* w_eval */
- /* */
- /* Evaluate the test board according to white's favor. Return */
- /* an integer denoting how good the position is. This should */
- /* be identical to the other one, except that all of the loops */
- /* and values are reversed. Note, though, that taking the neg */
- /* of b_eval is not the same thing! Also, since they should be */
- /* close to the same, it is easy to test changes by making them */
- /* to one or the other evaluator, and letting the machine play */
- /* against itself for 100 games or so (overnight). */
- /* */
- /****************************************************************/
-
- w_eval( test, count )
-
- int test[ SIZE ][ 3 ], count;
-
- {
-
- char buf[ 80 ];
- int i, j, watch_it, score, quad, end_game, hit_val;
-
- score = 0;
-
- /* If we are heavy into testing, spit */
- /* out the entire board in decimal. */
-
- if ( debug == 3 )
- {
- char_at( 21, 0, CTEOL, 0x07 );
- for( i = 0; i < 26; i++ )
- printf( "%02d ", test[ i ][ WHITE ] );
- char_at( 22, 0, CTEOL, 0x07 );
- for( i = 0; i < 26; i++ )
- printf( "%02d ", test[ i ][ BLACK ] );
- char_at( 23, 0, CTEOL, 0x07 );
- for( i = 0; i < 26; i++ )
- printf( "%02d ", test[ i ][ 2 ] );
- raw_keyboard();
- }
-
- /* Let them know we are still working */
- /* on a solution... */
-
- if ( count == 80 )
- write_at( 15, 65, "Hmmm.......", TEXT_COLOR );
-
- /* Test exception # 0 - we are in the */
- /* black's inner table, but we're going */
- /* to lose bad. in that case, we want */
- /* to hit anything we can! */
-
- for ( i = 0; i < 15; i++ )
- if ( test[ i ][ BLACK ] )
- break;
-
- if ( i == 15 )
- for ( ; i < 25; i++ )
- if ( test[ i ][ 2 ] )
- score = 30000;
-
- /* Look for another exception - we may */
- /* be almost off of the board, but then */
- /* leave one and only one man open on a */
- /* particular bar. If that's the case, */
- /* we don't want to do that... */
-
- for( i = 1; i < 9; i++ )
- if ( test[ i ][ WHITE ] == 1 )
- break;
-
- if ( i < 9 )
- {
-
- watch_it = FALSE;
-
- for( j = 1; j < 25; j++ )
- if ( test[ j ][ 2 ] )
- {
- watch_it = TRUE;
- break;
- }
-
- for( j = 0; j < i; j++ )
- if ( test[ j ][ BLACK ] )
- {
- watch_it = TRUE;
- break;
- }
-
- for( j = 9; j < 25; j++ )
- if ( test[ j ][ WHITE ] )
- {
- watch_it = FALSE;
- break;
- }
-
- if ( watch_it )
- score = -30000;
-
- } /* exception 1 */
-
- /* Detect the end-game situation. */
-
- for( i = 24; i; i-- )
- if ( test[ i ][ WHITE ] )
- break;
-
- for( end_game = TRUE; i; i-- )
- if ( ( test[ i ][ BLACK ] ) ||
- ( test[ i ][ 2 ] ) )
- {
- end_game = FALSE;
- break;
- }
-
- if ( end_game )
- {
-
- for( i = 24; i > 6; i-- )
- score -= test[ i ][ WHITE ] * i;
- for( ; i; i-- )
- score -= test[ i ][ WHITE ];
- return( score );
-
- } /* end_game */
- else
- {
-
- for( i = 1; i < 25; i++ )
- {
-
- quad = ( ( i - 1 ) / 6 ) + 1;
-
- if ( test[ i ][ WHITE ] == 1 )
- {
-
- hit_val = ( 18 - i );
- for( j = i - 1; ( j > -1 ) && ( j > i - 12 ); j-- )
- switch( test[ j ][ BLACK ] )
- {
-
- case 0: break;
-
-
- case 1: hit_val += prob[ i - j ];
- break;
-
- case 2: hit_val += prob[ i - j ] / 2;
- break;
-
- default: hit_val += prob[ i - j ] * 2;
-
- } /* switch */
-
- score -= hit_val * ( 4 - quad );
-
- } /* if */
-
- if ( test[ i ][ WHITE ] > 1 )
- {
- score += ( 18 - i );
- score += ( 4 - quad ) * 5;
- }
-
- /* Hit the black guys? */
-
- if ( test[ i ][ 2 ] )
- {
-
- score += quad * 15;
- for( j = 1; j < 9; j++ )
- if ( test[ j ][ WHITE ] > 1 )
- score += 5;
- else
- if ( test[ j ][ WHITE ] == 1 )
- score -= 3;
-
- } /* test inner tbl */
-
- } /* for i */
-
- return( score );
-
- } /* not end game */
-
- } /* w_eval */
-